/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
 * MA  02110-1301, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package parser.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import parser.clientData.clientAirline.ClientAirline;
import parser.clientData.clientAirline.ClientAirlineLoader;
import parser.clientData.clientAirports.ClientAirport;
import parser.clientData.clientAirports.ClientAirportsLoader;
import parser.clientData.clientGather.GatherSrc;
import parser.clientData.clientGather.GatherSrcLoader;
import parser.clientData.clientItems.ClientItem;
import parser.clientData.clientItems.ClientItemsLoader;
import parser.clientData.clientNpc.ClientNpcLoader;
import parser.clientData.clientNpc.NpcClient;
import parser.clientData.clientSkills.ClientSkillLoader;
import parser.clientData.clientSkills.SkillBaseClient;
import parser.clientData.clientStrings.ClientString;
import parser.clientData.clientStrings.ClientStringLoader;
import parser.clientData.clientWorldId.Data;
import parser.clientData.clientWorldId.WorldIdLoader;
import parser.clientData.collectedNpcData.CollectedNpcDataLoader;
import parser.clientData.collectedNpcData.NpcStat;
import parser.clientData.goodlist.ClientNpcGoodslist;
import parser.clientData.goodlist.GoodListLoader;
import parser.clientData.recipe.ClientCombineRecipe;
import parser.clientData.recipe.RecipeLoader;
import parser.clientData.skillLearns.ClientSkillLearn;
import parser.clientData.skillLearns.ClientSkillLearnsLoader;
import parser.clientData.tribeRelation.Tribe;
import parser.clientData.tribeRelation.TribeRelationLoader;
import parser.serverData.spawns.SpawnGroup;
import parser.serverData.spawns.SpawnLoader;

/**
 * @author Mr. Poke
 *
 */
public class DataManager
{

	private Map<String, ClientString>	stringNameMap;
	private List<Tribe>					tribeRelations;
	private List<NpcClient>				clientNpcs;
	private List<ClientItem>	itemList;
	private Map<Integer, ClientItem>	idItemMap;
	private List<Data>					worldIds;
	private Map<String, Integer>		itemNameIdMap;
	private Map<String, Integer>		npcNameIdMap;
	private Map<Integer, GatherSrc>		idGatherebleMap;
	private Map<String, Integer>		nameGatherebleIdMap;
	private Map<Integer, List<SpawnGroup>> spawnGroup;
	private Map<Integer, NpcStat> collectedNpcData;
	private Map<String, ClientAirline> clientAirline;
	private Map<String, ClientAirport> clientAirports;
	private Map<String, Tribe>					tribeMap;
	private Map<String, ClientNpcGoodslist> goodMap;
	private List<SkillBaseClient>					clientSkills;
	private Map<String, SkillBaseClient>					clientSkillsnameMap;
	private List<ClientSkillLearn> clientSkillLearn;
	private List<ClientCombineRecipe> recipeList;
	private Map<String,ClientCombineRecipe> recipeNameMap;
	public static final DataManager getInstance()
	{
		return SingletonHolder.instance;
	}

	private DataManager()
	{
	}

	/**
	 * @return Returns the stringNameMap.
	 */
	public Map<String, ClientString> getStringNameMap()
	{
		if (stringNameMap == null)
			stringNameMap = ClientStringLoader.load();
		return stringNameMap;
	}

	/**
	 * @return Returns the tribeRelations.
	 */
	public List<Tribe> getTribeRelations()
	{
		if (tribeRelations == null)
			tribeRelations = TribeRelationLoader.load();
		return tribeRelations;
	}

	public List<NpcClient> getNpcs()
	{
		if (clientNpcs == null)
			clientNpcs = ClientNpcLoader.load();
		
		return clientNpcs;
	}

	/**
	 * @return Returns the idItemMap.
	 */
	public Map<Integer, ClientItem> getIdItemMap()
	{
		if (idItemMap == null)
		{
			idItemMap = new HashMap<Integer, ClientItem>();
			for (ClientItem item : getItemList())
			{
				idItemMap.put(item.getId(), item);
			}
		}
		return idItemMap;
	}

	/**
	 * @return Returns the itemList.
	 */
	public List<ClientItem> getItemList()
	{
		if (itemList == null)
			itemList = ClientItemsLoader.load();
		return itemList;
	}

	/**
	 * @return Returns the itemNameIdMap.
	 */
	public Map<String, Integer> getItemNameIdMap()
	{
		if (itemNameIdMap == null)
			createItemNameIdMap();
		return itemNameIdMap;
	}

	/**
	 * @return Returns the npcNameIdMap.
	 */
	public Map<String, Integer> getNpcNameIdMap()
	{
		if (npcNameIdMap == null)
			createNpcNameIdMap();
		return npcNameIdMap;
	}

	public NpcStat getCollectedNpcData(int id)
	{
		if (collectedNpcData == null)
			collectedNpcData = CollectedNpcDataLoader.load();
		return collectedNpcData.get(id);
	}
	/**
	 * @return Returns the worldIds.
	 */
	public List<Data> getWorldIds()
	{
		if (worldIds == null)
			worldIds = WorldIdLoader.load();
		return worldIds;
	}

	private void createNpcNameIdMap()
	{
		npcNameIdMap = new HashMap<String, Integer>();
		for (NpcClient npc : getNpcs())
		{
			npcNameIdMap.put(npc.getName().toLowerCase(), npc.getId());
		}
	}

	private void createItemNameIdMap()
	{
		itemNameIdMap = new HashMap<String, Integer>();
		for (ClientItem item : getIdItemMap().values())
		{
			itemNameIdMap.put(item.getName().toLowerCase(), item.getId());
			if (item.getMesh() != null)
				itemNameIdMap.put(item.getMesh().toLowerCase(), item.getId());
		}
		itemNameIdMap.put("npc_rb_grove_petseller_01", 111101105);
		itemNameIdMap.put("npc_rb_grove_d_petseller_01", 111101106);
	}

	/**
	 * @return Returns the idGatherebleMap.
	 */
	public Map<Integer, GatherSrc> getIdGatherebleMap()
	{
		if (idGatherebleMap == null)
			idGatherebleMap = GatherSrcLoader.load();
		return idGatherebleMap;
	}

	/**
	 * @return Returns the nameGatherebleIdMap.
	 */
	public Map<String, Integer> getNameGatherebleIdMap()
	{
		nameGatherebleIdMap = new HashMap<String, Integer>();
		for (GatherSrc item : getIdGatherebleMap().values())
		{
			nameGatherebleIdMap.put(item.getName().toLowerCase(), item.getId());
		}
		return nameGatherebleIdMap;
	}

	/**
	 * @return Returns the spawnGroup.
	 */
	public Map<Integer, List<SpawnGroup>> getSpawnGroup()
	{
		if (spawnGroup == null)
			spawnGroup = SpawnLoader.load();
		return spawnGroup;
	}

	/**
	 * @return Returns the clientAirline.
	 */
	public Map<String, ClientAirline> getClientAirline()
	{
		if (clientAirline == null)
			clientAirline = ClientAirlineLoader.load();
		return clientAirline;
	}

	/**
	 * @return Returns the clientAirports.
	 */
	public Map<String, ClientAirport> getClientAirports()
	{
		if (clientAirports == null)
			clientAirports = ClientAirportsLoader.load();
		return clientAirports;
	}

	public String getBaseTribe (String tribe)
	{
		if (tribeMap == null)
		{
			tribeMap = new HashMap<String, Tribe>();
			for (Tribe tribes : this.getTribeRelations())
			{
				tribeMap.put(tribes.getTribe().toUpperCase(), tribes);
			}
		}
		while (true)
		{
			Tribe tribe2 = tribeMap.get(tribe);
			if (tribe2 == null)
			{
				return tribe;
			}
			else if (tribe2.getBaseTribe() != null)
				tribe = tribe2.getBaseTribe();
			else
				return tribe;
		}
	}

	/**
	 * @return Returns the goodMap.
	 */
	public Map<String, ClientNpcGoodslist> getGoodMap()
	{
		if (goodMap == null)
			goodMap = GoodListLoader.load();
		return goodMap;
	}

	/**
	 * @return Returns the clientSkills.
	 */
	public List<SkillBaseClient> getClientSkills()
	{
		if (clientSkills == null)
			clientSkills = ClientSkillLoader.load();
		return clientSkills;
	}

	/**
	 * @return Returns the clientSkillsnameMap.
	 */
	public Map<String, SkillBaseClient> getClientSkillsnameMap()
	{
		if (clientSkillsnameMap == null)
		{
			clientSkillsnameMap = new HashMap<String, SkillBaseClient>();
			for (SkillBaseClient skill : getClientSkills())
			{
				clientSkillsnameMap.put(skill.getName().toUpperCase(), skill);
			}
		}
		return clientSkillsnameMap;
	}

	/**
	 * @return Returns the clientSkillLearn.
	 */
	public List<ClientSkillLearn> getClientSkillLearn()
	{
		if (clientSkillLearn == null)
			clientSkillLearn = ClientSkillLearnsLoader.load();
		return clientSkillLearn;
	}

	/**
	 * @return Returns the recipeList.
	 */
	public List<ClientCombineRecipe> getRecipeList()
	{
		if (recipeList == null)
			recipeList = RecipeLoader.load();
		return recipeList;
	}

	/**
	 * @return Returns the recipeNameMap.
	 */
	public Map<String, ClientCombineRecipe> getRecipeNameMap()
	{
		if (recipeNameMap == null)
		{
			recipeNameMap = new HashMap<String, ClientCombineRecipe>();
			for (ClientCombineRecipe recipe : getRecipeList())
				recipeNameMap.put(recipe.getName().toLowerCase(), recipe);
		}
		return recipeNameMap;
	}

	@SuppressWarnings("synthetic-access")
	private static class SingletonHolder
	{
		protected static final DataManager	instance	= new DataManager();
	}
}
